In [1]:
import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import folium # for leaflet maps

from IPython.display import HTML

HTML('''<script>
code_show=true; 
function code_toggle() {
 if (code_show){
 $('div.input').hide();
 } else {
 $('div.input').show();
 }
 code_show = !code_show
} 
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Click to show/unshow codes."></form>''')
Out[1]:

1. Basic reporting

Here we will use the public data provided by JHU. The data and visualization are updated daily. https://github.com/CSSEGISandData/COVID-19

In [2]:
# read data
full_table = pd.read_csv('covid_19_clean_complete.csv', parse_dates=['Date'])

# combine china and mainland china
full_table['Country/Region'].replace({'China':'Mainland China'},inplace=True)
countries = full_table['Country/Region'].unique().tolist()

# filling missing values
full_table[['Province/State']] = full_table[['Province/State']].fillna('--')

print("\nTotal countries affected by CoVID-19 thus far: ",len(countries))
Total countries affected by CoVID-19 thus far:  53
In [3]:
# cases in the Diamond Princess cruise ship
ship = full_table[full_table['Province/State']=='Diamond Princess cruise ship']
full_table = full_table[full_table['Province/State']!='Diamond Princess cruise ship']

# cases in china vs outside china
china = full_table[full_table['Country/Region']=='Mainland China']
row = full_table[full_table['Country/Region']!='Mainland China']

# latest numbers (cumulative)
full_latest = full_table[full_table['Date'] == max(full_table['Date'])].reset_index()
china_latest = full_latest[full_latest['Country/Region']=='Mainland China']
row_latest = full_latest[full_latest['Country/Region']!='Mainland China']

full_latest_grouped = full_latest.groupby('Country/Region')['Confirmed', 'Deaths', 'Recovered'].sum().reset_index()
china_latest_grouped = china_latest.groupby('Province/State')['Confirmed', 'Deaths', 'Recovered'].sum().reset_index()
row_latest_grouped = row_latest.groupby('Country/Region')['Confirmed', 'Deaths', 'Recovered'].sum().reset_index()

1.1. Summary statistics for the past 5 days

In [4]:
# global data
all_cases = full_table.groupby('Date')['Confirmed', 'Deaths', 'Recovered'].sum()
all_cases = all_cases.reset_index()
all_cases = all_cases.sort_values('Date', ascending=False)
all_cases.head(5).style.background_gradient(cmap='Pastel1')
Out[4]:
Date Confirmed Deaths Recovered
36 2020-02-27 00:00:00 82051 2810 33267
35 2020-02-26 00:00:00 80692 2766 30374
34 2020-02-25 00:00:00 79724 2705 27905
33 2020-02-24 00:00:00 78879 2626 25227
32 2020-02-23 00:00:00 78294 2466 23394

1.2. Current status: breakdown by countries (alphabetical)

In [5]:
# breakdown by countries, alphabetical
temp = full_latest.groupby(['Country/Region', 'Province/State'])['Confirmed', 'Deaths', 'Recovered'].max()
temp.style.background_gradient(cmap='Pastel1_r')
Out[5]:
Confirmed Deaths Recovered
Country/Region Province/State
Afghanistan -- 1 0 0
Algeria -- 1 0 0
Australia From Diamond Princess 8 0 0
New South Wales 4 0 4
Queensland 5 0 1
South Australia 2 0 2
Victoria 4 0 4
Austria -- 3 0 0
Bahrain -- 33 0 0
Belgium -- 1 0 1
Brazil -- 1 0 0
Cambodia -- 1 0 1
Canada British Columbia 7 0 3
London, ON 1 0 1
Toronto, ON 5 0 2
Croatia -- 3 0 0
Denmark -- 1 0 0
Egypt -- 1 0 0
Estonia -- 1 0 0
Finland -- 2 0 1
France -- 38 2 11
Georgia -- 1 0 0
Germany -- 46 0 16
Greece -- 3 0 0
Hong Kong Hong Kong 92 2 24
India -- 3 0 3
Iran -- 245 26 49
Iraq -- 7 0 0
Israel -- 3 0 1
Italy -- 655 17 45
Japan -- 214 4 22
Kuwait -- 43 0 0
Lebanon -- 2 0 0
Macau Macau 10 0 8
Mainland China Anhui 989 6 792
Beijing 410 5 248
Chongqing 576 6 401
Fujian 296 1 228
Gansu 91 2 81
Guangdong 1347 7 890
Guangxi 252 2 161
Guizhou 146 2 112
Hainan 168 5 131
Hebei 317 6 274
Heilongjiang 480 13 270
Henan 1272 20 1068
Hubei 65596 2641 23383
Hunan 1017 4 804
Inner Mongolia 75 0 43
Jiangsu 631 0 498
Jiangxi 934 1 754
Jilin 93 1 67
Liaoning 121 1 93
Ningxia 72 0 68
Qinghai 18 0 18
Shaanxi 245 1 195
Shandong 756 6 387
Shanghai 337 3 276
Shanxi 133 0 107
Sichuan 534 3 321
Tianjin 136 3 102
Tibet 1 0 1
Xinjiang 76 2 43
Yunnan 174 2 150
Zhejiang 1205 1 932
Malaysia -- 23 0 18
Nepal -- 1 0 1
Netherlands -- 1 0 0
North Macedonia -- 1 0 0
Norway -- 1 0 0
Oman -- 4 0 0
Pakistan -- 2 0 0
Philippines -- 3 1 1
Romania -- 1 0 0
Russia -- 2 0 2
San Marino -- 1 0 0
Singapore -- 93 0 62
South Korea -- 1766 13 22
Spain -- 15 0 2
Sri Lanka -- 1 0 1
Sweden -- 7 0 0
Switzerland -- 8 0 0
Taiwan Taiwan 32 1 5
Thailand -- 40 0 22
UK -- 15 0 8
US Boston, MA 1 0 0
Chicago, IL 2 0 2
Humboldt County, CA 1 0 0
Lackland, TX (From Diamond Princess) 0 0 0
Los Angeles, CA 1 0 0
Madison, WI 1 0 0
Omaha, NE (From Diamond Princess) 0 0 0
Orange, CA 1 0 0
Sacramento County, CA 2 0 0
San Antonio, TX 1 0 0
San Benito, CA 2 0 0
San Diego County, CA 2 0 1
Santa Clara, CA 2 0 1
Seattle, WA 1 0 1
Tempe, AZ 1 0 1
Travis, CA (From Diamond Princess) 0 0 0
Unassigned Location (From Diamond Princess) 42 0 0
United Arab Emirates -- 13 0 4
Vietnam -- 16 0 16

1.3. Current standing (sorted by # cases)

In [6]:
# breakdown by countries, sorted by cases

temp_f = full_latest_grouped[['Country/Region', 'Confirmed', 'Deaths', 'Recovered']]
temp_f = temp_f.sort_values(by='Confirmed', ascending=False)
temp_f = temp_f.reset_index(drop=True)
temp_f.style.background_gradient(cmap='Pastel1_r')
Out[6]:
Country/Region Confirmed Deaths Recovered
0 Mainland China 78498 2744 32898
1 South Korea 1766 13 22
2 Italy 655 17 45
3 Iran 245 26 49
4 Japan 214 4 22
5 Singapore 93 0 62
6 Hong Kong 92 2 24
7 US 60 0 6
8 Germany 46 0 16
9 Kuwait 43 0 0
10 Thailand 40 0 22
11 France 38 2 11
12 Bahrain 33 0 0
13 Taiwan 32 1 5
14 Australia 23 0 11
15 Malaysia 23 0 18
16 Vietnam 16 0 16
17 Spain 15 0 2
18 UK 15 0 8
19 Canada 13 0 6
20 United Arab Emirates 13 0 4
21 Macau 10 0 8
22 Switzerland 8 0 0
23 Iraq 7 0 0
24 Sweden 7 0 0
25 Oman 4 0 0
26 Philippines 3 1 1
27 Greece 3 0 0
28 Israel 3 0 1
29 India 3 0 3
30 Croatia 3 0 0
31 Austria 3 0 0
32 Russia 2 0 2
33 Pakistan 2 0 0
34 Lebanon 2 0 0
35 Finland 2 0 1
36 Norway 1 0 0
37 Belgium 1 0 1
38 Brazil 1 0 0
39 Cambodia 1 0 1
40 Denmark 1 0 0
41 Egypt 1 0 0
42 Estonia 1 0 0
43 Sri Lanka 1 0 1
44 North Macedonia 1 0 0
45 Georgia 1 0 0
46 Algeria 1 0 0
47 Nepal 1 0 1
48 San Marino 1 0 0
49 Netherlands 1 0 0
50 Romania 1 0 0
51 Afghanistan 1 0 0

1.4. Breakdown of cases in Mainland China by province

In [7]:
# breakdown of cases in China by provinces

temp_f = china_latest_grouped[['Province/State', 'Confirmed', 'Deaths', 'Recovered']]
temp_f = temp_f.sort_values(by='Confirmed', ascending=False)
temp_f = temp_f.reset_index(drop=True)
temp_f.style.background_gradient(cmap='Pastel1_r')
Out[7]:
Province/State Confirmed Deaths Recovered
0 Hubei 65596 2641 23383
1 Guangdong 1347 7 890
2 Henan 1272 20 1068
3 Zhejiang 1205 1 932
4 Hunan 1017 4 804
5 Anhui 989 6 792
6 Jiangxi 934 1 754
7 Shandong 756 6 387
8 Jiangsu 631 0 498
9 Chongqing 576 6 401
10 Sichuan 534 3 321
11 Heilongjiang 480 13 270
12 Beijing 410 5 248
13 Shanghai 337 3 276
14 Hebei 317 6 274
15 Fujian 296 1 228
16 Guangxi 252 2 161
17 Shaanxi 245 1 195
18 Yunnan 174 2 150
19 Hainan 168 5 131
20 Guizhou 146 2 112
21 Tianjin 136 3 102
22 Shanxi 133 0 107
23 Liaoning 121 1 93
24 Jilin 93 1 67
25 Gansu 91 2 81
26 Xinjiang 76 2 43
27 Inner Mongolia 75 0 43
28 Ningxia 72 0 68
29 Qinghai 18 0 18
30 Tibet 1 0 1

2. Map of reported cases

For the dashboard by JHU see https://www.arcgis.com/apps/opsdashboard/index.html#/bda7594740fd40299423467b48e9ecf6

2.1. Latest number of cases by countries/provinces

In [8]:
rl = row_latest.groupby('Country/Region')['Confirmed', 'Deaths', 'Recovered'].sum()
rl = rl.reset_index().sort_values(by='Confirmed', ascending=False).reset_index(drop=True)

ncl = rl.copy()
ncl['Affected'] = ncl['Confirmed'] - ncl['Deaths'] - ncl['Recovered']
ncl = ncl.melt(id_vars="Country/Region", value_vars=['Affected', 'Recovered', 'Deaths'])

fig = px.bar(ncl.sort_values(['variable', 'value']), 
             x="value", y="Country/Region", color='variable', orientation='h', height=800,
             # height=600, width=1000,
             title='Number of cases (excluding China)')
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')
fig.show()

# ------------------------------------------

cl = china_latest.groupby('Province/State')['Confirmed', 'Deaths', 'Recovered'].sum()
cl = cl.reset_index().sort_values(by='Confirmed', ascending=False).reset_index(drop=True)
# cl.head().style.background_gradient(cmap='rainbow')

ncl = cl.copy()
ncl['Affected'] = ncl['Confirmed'] - ncl['Deaths'] - ncl['Recovered']
ncl = ncl.melt(id_vars="Province/State", value_vars=['Affected', 'Recovered', 'Deaths'])

fig = px.bar(ncl.sort_values(['variable', 'value']), 
             y="value", x="Province/State", color='variable', orientation='v', height=800,
             # height=600, width=1000,
             title='Number of cases in China')
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')
fig.show()

2.2 Map of reported cases

In [9]:
# map of reported cases worldwide

m = folium.Map(location=[10, -20], tiles='openstreetmap',
               min_zoom=1, max_zoom=4, zoom_start=2.3)

for i in range(0, len(full_latest)):
    folium.CircleMarker(
        location=[full_latest.iloc[i]['Lat'], full_latest.iloc[i]['Long']],
        color='crimson', 
        tooltip =   '<li><bold>Country : '+str(full_latest.iloc[i]['Country/Region'])+
                    '<li><bold>Province : '+str(full_latest.iloc[i]['Province/State'])+
                    '<li><bold>Confirmed : '+str(full_latest.iloc[i]['Confirmed'])+
                    '<li><bold>Deaths : '+str(full_latest.iloc[i]['Deaths'])+
                    '<li><bold>Recovered : '+str(full_latest.iloc[i]['Recovered']),
        radius=int(full_latest.iloc[i]['Confirmed']**0.2 + 1),
        fill_color='red',
        fill_opacity=0.7).add_to(m)
m
Out[9]:

2.3. Spread of CoVID-19 over time

In [10]:
formated_gdf = row.groupby(['Date', 'Country/Region'])['Confirmed', 'Deaths', 'Recovered'].max()
formated_gdf = formated_gdf.reset_index()
formated_gdf = formated_gdf[formated_gdf['Country/Region']!='Mainland China']
formated_gdf['Date'] = pd.to_datetime(formated_gdf['Date'])
formated_gdf['Date'] = formated_gdf['Date'].dt.strftime('%m/%d/%Y')

fig = px.scatter_geo(formated_gdf[formated_gdf['Country/Region']!='China'], 
                     locations="Country/Region", locationmode='country names', 
                     color="Confirmed", size='Confirmed', hover_name="Country/Region", 
                     range_color= [0, max(formated_gdf['Confirmed'])+2], 
                     projection="natural earth", animation_frame="Date", 
                     title='Spread outside China over time')
fig.update(layout_coloraxis_showscale=False)
fig.show()

# -----------------------------------------------------------------------------------

china_map = china.groupby(['Date', 'Province/State'])['Confirmed', 'Deaths', 'Recovered', 
                                                      'Lat', 'Long'].max()
china_map = china_map.reset_index()
china_map['size'] = china_map['Confirmed'].pow(0.5)
china_map['Date'] = pd.to_datetime(china_map['Date'])
china_map['Date'] = china_map['Date'].dt.strftime('%m/%d/%Y')
china_map.head()

fig = px.scatter_geo(china_map, lat='Lat', lon='Long', scope='asia',
                     color="size", size='size', hover_name='Province/State', 
                     hover_data=['Confirmed', 'Deaths', 'Recovered'],
                     projection="natural earth", animation_frame="Date", 
                     title='Spread in China over time')
fig.update(layout_coloraxis_showscale=False)
fig.show()

2.4. Countries with highest number of deaths

In [11]:
# countries by highest deaths
temp_flg = full_latest_grouped[['Country/Region', 'Deaths']]
temp_flg = temp_flg.sort_values(by='Deaths', ascending=False)
temp_flg = temp_flg.reset_index(drop=True)
temp_flg = temp_flg[temp_flg['Deaths']>0]
temp_flg.style.background_gradient(cmap='Pastel1_r')
Out[11]:
Country/Region Deaths
0 Mainland China 2744
1 Iran 26
2 Italy 17
3 South Korea 13
4 Japan 4
5 Hong Kong 2
6 France 2
7 Taiwan 1
8 Philippines 1

2.5. Countries with no recovered cases

In [12]:
# Countries with no cases recovered (yet)
temp = row_latest_grouped[row_latest_grouped['Recovered']==0]
temp = temp[['Country/Region', 'Confirmed', 'Deaths', 'Recovered']]
temp = temp.sort_values('Confirmed', ascending=False)
temp = temp.reset_index(drop=True)
temp.style.background_gradient(cmap='Pastel1_r')
Out[12]:
Country/Region Confirmed Deaths Recovered
0 Kuwait 43 0 0
1 Bahrain 33 0 0
2 Switzerland 8 0 0
3 Sweden 7 0 0
4 Iraq 7 0 0
5 Oman 4 0 0
6 Croatia 3 0 0
7 Austria 3 0 0
8 Greece 3 0 0
9 Pakistan 2 0 0
10 Lebanon 2 0 0
11 North Macedonia 1 0 0
12 San Marino 1 0 0
13 Romania 1 0 0
14 Norway 1 0 0
15 Netherlands 1 0 0
16 Denmark 1 0 0
17 Brazil 1 0 0
18 Algeria 1 0 0
19 Georgia 1 0 0
20 Estonia 1 0 0
21 Egypt 1 0 0
22 Afghanistan 1 0 0

2.6 Countries with all affected recovered/died

In [13]:
temp = row_latest_grouped[row_latest_grouped['Confirmed']==
                          row_latest_grouped['Deaths']+
                          row_latest_grouped['Recovered']]
temp = temp[['Country/Region', 'Confirmed', 'Deaths', 'Recovered']]
temp = temp.sort_values('Confirmed', ascending=False)
temp = temp.reset_index(drop=True)
temp.style.background_gradient(cmap='Greens')
Out[13]:
Country/Region Confirmed Deaths Recovered
0 Vietnam 16 0 16
1 India 3 0 3
2 Russia 2 0 2
3 Belgium 1 0 1
4 Cambodia 1 0 1
5 Nepal 1 0 1
6 Sri Lanka 1 0 1

2.7. Chinese provinces with all affected recovered/died

In [14]:
temp = china_latest_grouped[china_latest_grouped['Confirmed']==
                          china_latest_grouped['Deaths']+
                          china_latest_grouped['Recovered']]
temp = temp[['Province/State', 'Confirmed', 'Deaths', 'Recovered']]
temp = temp.sort_values('Confirmed', ascending=False)
temp = temp.reset_index(drop=True)
temp.style.background_gradient(cmap='Greens')
Out[14]:
Province/State Confirmed Deaths Recovered
0 Qinghai 18 0 18
1 Tibet 1 0 1
In [15]:
# Cases in the Diamond Princess Cruise Ship
temp = ship.sort_values(by='Date', ascending=False).head(1)
temp = temp[['Province/State', 'Date', 'Confirmed', 'Deaths', 'Recovered']].reset_index(drop=True)
temp.style.background_gradient(cmap='rainbow')
Out[15]:
Province/State Date Confirmed Deaths Recovered
0 Diamond Princess cruise ship 2020-02-27 00:00:00 705 4 10

3. Comparing hotspots

3.1. Hubei/Rest of China/Rest of the World

In [16]:
def location(row):
    if row['Country/Region']=='Mainland China':
        if row['Province/State']=='Hubei':
            return 'Hubei'
        else:
            return 'Other Chinese Provinces'
    else:
        return 'Rest of the World'

temp = full_latest.copy()
temp['Region'] = temp.apply(location, axis=1)
temp = temp.groupby('Region')['Confirmed', 'Deaths', 'Recovered'].sum().reset_index()
temp = temp.melt(id_vars='Region', value_vars=['Confirmed', 'Deaths', 'Recovered'], 
                 var_name='Case', value_name='Count').sort_values('Count')

fig = px.bar(temp, y='Region', x='Count', color='Case', barmode='group', orientation='h',
             text='Count', title='Hubei - Rest of China - Rest of the World', 
             color_discrete_sequence= ['#EF553B', '#00CC96', '#636EFA'])
fig.update_traces(textposition='outside')
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')
fig.show()

3.2. Number of total cases in time

In [17]:
gdf = full_table.groupby(['Date', 'Country/Region'])['Confirmed', 'Deaths', 'Recovered'].max()
gdf = gdf.reset_index()

temp = gdf[gdf['Country/Region']=='Mainland China'].reset_index()
temp = temp.melt(id_vars='Date', value_vars=['Confirmed', 'Deaths', 'Recovered'],
                var_name='Case', value_name='Count')
fig = px.bar(temp, x="Date", y="Count", color='Case', facet_col="Case",
            title='Cases in China')
fig.show()

temp = gdf[gdf['Country/Region']!='Mainland China'].groupby('Date').sum().reset_index()
temp = temp.melt(id_vars='Date', value_vars=['Confirmed', 'Deaths', 'Recovered'],
                var_name='Case', value_name='Count')
fig = px.bar(temp, x="Date", y="Count", color='Case', facet_col="Case",
             title='Cases in rest of the World')
fig.show()

3.3 Number of countries affected by CoVID-19 in time

Note that China has 31 administrative divisions (省级行政区) under direct jurisdiction (excluding Hong Kong and Macau). https://en.wikipedia.org/wiki/Provinces_of_China

In [18]:
c_spread = china[china['Confirmed']!=0].groupby('Date')['Province/State'].unique().apply(len)
c_spread = pd.DataFrame(c_spread).reset_index()

fig = px.line(c_spread, x='Date', y='Province/State', 
              title='Number of provinces in China affected over time')
fig.show()

# ------------------------------------------------------------------------------------------

spread = full_table[full_table['Confirmed']!=0].groupby('Date')['Country/Region'].unique().apply(len)
spread = pd.DataFrame(spread).reset_index()

fig = px.line(spread, x='Date', y='Country/Region', 
              title='Number of countries affected over time')
fig.show()

3.4. Recovery and mortality rate over time

In [19]:
temp = full_table.groupby('Date').sum().reset_index()
temp.head()

# adding two more columns
temp['% death'] = round(temp['Deaths']/
                                                     temp['Confirmed'], 3)*100
temp['% recovered'] = round(temp['Recovered']/
                                                        temp['Confirmed'], 3)*100

temp = temp.melt(id_vars='Date', 
                 value_vars=['% death', 
                             '% recovered'], 
                 var_name='Ratio', 
                 value_name='Value')

fig = px.line(temp, x="Date", y="Value", color='Ratio', 
              title='Recovery and Mortality Rate over Time')
fig.show()

3.5 Treemap of countries with reported cases

In [20]:
fig = px.treemap(china_latest.sort_values(by='Confirmed', ascending=False).reset_index(drop=True), 
                 path=["Province/State"], values="Confirmed", 
                 title='Number of Confirmed Cases in Chinese Provinces',
                 color_discrete_sequence = px.colors.qualitative.Prism)
fig.show()

fig = px.treemap(china_latest.sort_values(by='Deaths', ascending=False).reset_index(drop=True), 
                 path=["Province/State"], values="Deaths", 
                 title='Number of Deaths Reported in Chinese Provinces',
                 color_discrete_sequence = px.colors.qualitative.Prism)
fig.show()

fig = px.treemap(china_latest.sort_values(by='Recovered', ascending=False).reset_index(drop=True), 
                 path=["Province/State"], values="Recovered", 
                 title='Number of Recovered Cases in Chinese Provinces',
                 color_discrete_sequence = px.colors.qualitative.Prism)
fig.show()
In [21]:
fig = px.treemap(row_latest, path=["Country/Region"], values="Confirmed", 
                 title='# confirmed (excluding Mainland China)',
                 color_discrete_sequence = px.colors.qualitative.Pastel)
fig.show()

fig = px.treemap(row_latest, path=["Country/Region"], values="Deaths", 
                 title='# deaths (excluding Mainland China)',
                 color_discrete_sequence = px.colors.qualitative.Pastel)
fig.show()

fig = px.treemap(row_latest, path=["Country/Region"], values="Recovered", 
                 title='# recovered (excluding Mainland China)',
                 color_discrete_sequence = px.colors.qualitative.Pastel)
fig.show()

3.6. Number of new reported cases daily

In [22]:
temp = full_table.groupby(['Country/Region', 'Date', ])['Confirmed', 'Deaths', 'Recovered']
temp = temp.sum().diff().reset_index()

mask = temp['Country/Region'] != temp['Country/Region'].shift(1)

temp.loc[mask, 'Confirmed'] = np.nan
temp.loc[mask, 'Deaths'] = np.nan
temp.loc[mask, 'Recovered'] = np.nan

fig = px.bar(temp, x="Date", y="Confirmed", color='Country/Region',
             title='Number of new cases reported globally everyday')
fig.show()

fig = px.bar(temp[temp['Country/Region']!='Mainland China'], x="Date", y="Confirmed", color='Country/Region',
             title='Number of daily new cases (excluding) China')
fig.show()

fig = px.bar(temp[temp['Country/Region']!='Mainland China'], x="Date", y="Deaths", color='Country/Region',
             title='Number of daily new death cases (excluding China)')
fig.show()

4. Comparison with other epidemics

In [23]:
epidemics = pd.DataFrame({
    'epidemic' : ['COVID-19', 'SARS', 'EBOLA', 'MERS', 'H1N1'],
    'start_year' : [2019, 2003, 2014, 2012, 2009],
    'end_year' : [2020, 2004, 2016, 2017, 2010],
    'confirmed' : [80000, 8096, 28646, 2494, 6724149],
    'deaths' : [2750, 774, 11323, 858, 19654]
})

epidemics['% mortality'] = round((epidemics['deaths']/epidemics['confirmed'])*100, 2)

epidemics
Out[23]:
epidemic start_year end_year confirmed deaths % mortality
0 COVID-19 2019 2020 80000 2750 3.44
1 SARS 2003 2004 8096 774 9.56
2 EBOLA 2014 2016 28646 11323 39.53
3 MERS 2012 2017 2494 858 34.40
4 H1N1 2009 2010 6724149 19654 0.29
In [24]:
temp = epidemics.melt(id_vars='epidemic', value_vars=['confirmed', 'deaths', '% mortality'],
                      var_name='Case', value_name='Value')

fig = px.bar(temp, x="epidemic", y="Value", color='epidemic', text='Value', facet_col="Case",
             color_discrete_sequence = px.colors.qualitative.Bold)
fig.update_traces(textposition='outside')
fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide')
fig.update_yaxes(showticklabels=False)
fig.layout.yaxis2.update(matches=None)
fig.layout.yaxis3.update(matches=None)
fig.show()
In [25]:
temp = full_table.groupby('Date')['Confirmed'].sum().reset_index()

covid = temp['Confirmed']
sars = [8096 for i in range(len(temp))]
ebola = [28646 for i in range(len(temp))]
mers = [2494 for i in range(len(temp))]
h1n1 = [6724149 for i in range(len(temp))]

plt.style.use('fivethirtyeight')
plt.figure(figsize=(20, 8))
ax = plt.plot(temp['Date'], covid, label='COVID-19 (2019-2020)', c='#555555', alpha=0.8)
ax = plt.plot(temp['Date'], sars, label='SARS (2003-2004)', c='#E71D36', ls='--', alpha=0.8)
ax = plt.plot(temp['Date'], ebola, label='EBOLA (2014-2016)', c='#FF9F1C', ls='--', alpha=0.8)
ax = plt.plot(temp['Date'], mers, label='MERS (2012-2017)', c='#2EC4B6', ls='--', alpha=0.8)
plt.title('Number of cases (excluding H1N1)')
plt.legend()
plt.show()
/Users/kevinsiswandi/opt/anaconda3/lib/python3.7/site-packages/pandas/plotting/_matplotlib/converter.py:103: FutureWarning:

Using an implicitly registered datetime converter for a matplotlib plotting method. The converter was registered by pandas on import. Future versions of pandas will require you to explicitly register matplotlib converters.

To register the converters:
	>>> from pandas.plotting import register_matplotlib_converters
	>>> register_matplotlib_converters()

In [26]:
temp = full_table.groupby('Date')['Deaths'].sum().reset_index()

covid = temp['Deaths']
sars = [774 for i in range(len(temp))]
ebola = [11323 for i in range(len(temp))]
mers = [858 for i in range(len(temp))]
h1n1 = [19654 for i in range(len(temp))]

plt.figure(figsize=(20, 8))
ax = plt.plot(temp['Date'], covid, label='COVID-19 (2019-2020)', c='#555555', alpha=0.8)
ax = plt.plot(temp['Date'], sars, label='SARS (2003-2004)', c='#E71D36', ls='--', alpha=0.8)
ax = plt.plot(temp['Date'], ebola, label='EBOLA (2014-2016)', c='#FF9F1C', ls='--', alpha=0.8)
ax = plt.plot(temp['Date'], mers, label='MERS (2012-2017)', c='#2EC4B6', ls='--', alpha=0.8)
ax = plt.plot(temp['Date'], h1n1, label='H1N1 (2009-2010)', c='#2345BA', ls='--', alpha=0.8)
plt.title('Number of deaths')
plt.legend()
plt.show()
In [ ]: